package com.dyh.quickdemozwei.util;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;

import java.util.concurrent.TimeUnit;

/**
 * @Author: yhdong
 * @Date: 2021/12/1 15:47
 */
public class HttpClientWrap {

    private final HttpClient httpClient;
    private IdleConnectionMonitorThread idleConnectionMonitor;

    public HttpClientWrap(HttpClientCustom custom) {
        ConnectionKeepAliveStrategy keepAliveStrategy = new DefaultConnectionKeepAliveStrategy() {
            @Override
            public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
                long keepAlive = super.getKeepAliveDuration(response, context);
                if (keepAlive == -1) {
                    return custom.getKeepAliveTimeout();
                }
                return keepAlive;
            }
        };

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(custom.getConnectionMaxTotal());
        connectionManager.setDefaultMaxPerRoute(custom.getMaxPerRoute());

        this.httpClient = HttpClients.custom()
                .setConnectionManager(connectionManager)
                .setKeepAliveStrategy(keepAliveStrategy)
                .setDefaultRequestConfig(RequestConfig.custom()
                        .setConnectTimeout(custom.getConnectTimeout())
                        .setSocketTimeout(custom.getReadTimeout()).build())
                .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
                .build();

        this.idleConnectionMonitor = new IdleConnectionMonitorThread(connectionManager);
        this.idleConnectionMonitor.start();
    }


    public HttpClient client(){
        return this.httpClient;
    }

    public void shutdown(){
        this.idleConnectionMonitor.shutdown();
    }

    //用于监控空闲的连接池连接
    private final class IdleConnectionMonitorThread extends Thread {
        private final HttpClientConnectionManager connectionManager;
        private volatile boolean shutdown;



        public IdleConnectionMonitorThread(HttpClientConnectionManager connectionManager) {
            super();
            this.connectionManager = connectionManager;
            this.shutdown = false;
        }

        @Override
        public void run() {
            try {
                while (!shutdown) {
                    synchronized (this) {
                        wait(5000);
                        // 关闭无效的连接
                        connectionManager.closeExpiredConnections();
                        // 关闭空闲时间超过IDLE_ALIVE_MS的连接
                        connectionManager.closeIdleConnections(30, TimeUnit.SECONDS);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 关闭后台连接
        public void shutdown() {
            shutdown = true;
            synchronized (this) {
                notifyAll();
            }
        }
    }

}
